#include "FileOperator.h"
using namespace std;

FileOperator::FileOperator(string filename)
{
	this->fileName = filename;
}

FileOperator::~FileOperator(void)
{
}

void FileOperator::OutputVectors( string &vectorTitle, std::vector<std::vector<double>> &theVectors )
{
	fstream tofile;
	tofile.open(this->fileName.c_str(),ios::out | ios::trunc);
	if (!tofile) 
		PrintConsole::Error("cannot open or create file", this->fileName.c_str());
	tofile << vectorTitle <<std::endl;

	for (std::vector<double>::size_type ixVectors = 0; ixVectors != theVectors[0].size(); ++ixVectors)
	{
		for (std::vector<std::vector<double>>::size_type ix = 0; ix != theVectors.size(); ++ix)
		{
			tofile << theVectors[ix][ixVectors] << "\t\t";
		}
		tofile << std::endl;
	}
	tofile.close();
}

void FileOperator::Output2DVectorForMatlab(std::string &vectorTitle, My2DVector<double> the2DVector, bool newFile)
{
	fstream tofile;
	if (newFile)
	{
		tofile.open(this->fileName.c_str(),ios::out | ios::trunc);
	}
	else
	{
		tofile.open(this->fileName.c_str(),ios::app);
	}
	if (!tofile) 
		PrintConsole::Error("cannot open or create file", this->fileName.c_str());
	tofile << std::endl << vectorTitle <<std::endl;

	tofile << "[";
	for (int iy = 0; iy != the2DVector.ColSize; ++iy)
	{
		for (int ix = 0; ix != the2DVector.RowSize; ++ix)
		{
			tofile << the2DVector(ix, iy) << "\t";
		}
		tofile << ";" << std::endl;
	}
	tofile << "]" << std::endl;
	tofile.close();
}

void FileOperator::Output2DVectorsForOrigin(std::string &vectorTitle, std::vector<My2DVector<double>> the2Dvectors)
{
	fstream tofile;
	tofile.open(this->fileName.c_str(),ios::out | ios::trunc);
	if (!tofile) 
		PrintConsole::Error("cannot open or create file", this->fileName.c_str());
	tofile << vectorTitle <<std::endl;

	for (std::vector<double>::size_type ixVector = 0; ixVector != the2Dvectors[0].DataVector.size(); ++ixVector)
	{
		for (std::vector<My2DVector<double>>::size_type ix = 0; ix != the2Dvectors.size(); ++ix)
		{
			tofile << the2Dvectors[ix].DataVector[ixVector] << '\t';
		}
		tofile << std::endl;
	}
	tofile.close();
}

void FileOperator::ReadOneDimProblemInfo(int &gridnum, OneDimBC &left, OneDimBC &right)
{
	fstream infile;
	infile.open(this->fileName.c_str(),ios::in);
	if (!infile) 
		PrintConsole::Error("cannot open or create file", this->fileName.c_str());

	string aLineBuffer = "";
	stringstream ss;
	string tempstring = "";
	double tempdouble = 0;

	for (int theLineNumber = 1; theLineNumber <= this->infoLinesOneDim; ++theLineNumber)
	{
		getline(infile, aLineBuffer);
		ss.clear();
		ss.str(aLineBuffer);
		switch (theLineNumber)
		{
		case 1:
			ss >> gridnum;
			break;
		case 2:
			ss >> tempstring;
			if (tempstring == "First") 
			{
				left.Type = First;
			}
			else if (tempstring == "Second") 
			{
				left.Type = Second;
			}
			else 
				PrintConsole::Error("Wrong left boundary condition in", this->fileName.c_str());
			ss >> left.Value;

			break;
		case 3:
			ss >> tempstring;
			if (tempstring == "First") 
			{
				right.Type = First;
			}
			else if (tempstring == "Second") 
			{
				right.Type = Second;
			}
			else 
				PrintConsole::Error("Wrong right boundary condition in", this->fileName.c_str());
			ss >> right.Value;
			break;
		}
	}
	infile.close();
}

void FileOperator::ReadOneDimProblem( std::vector<double>& deltaX, std::vector<double>& relativeDiel, std::vector<double>& chargeConc )
{
	fstream infile;
	infile.open(this->fileName.c_str(), ios::in);
	if (!infile) 
		PrintConsole::Error("cannot open input file", this->fileName.c_str());

	string aLineBuffer = "";
	stringstream ss;

	for (int i=0; i<this->infoLinesOneDim; ++i)
	{
		getline(infile, aLineBuffer);//skip information line
	}
	int lineIndex = 0;
	while (getline(infile, aLineBuffer))
	{
		if (aLineBuffer == "") break;
		ss.clear();
		ss.str(aLineBuffer);
		ss >> deltaX[lineIndex] >> relativeDiel[lineIndex] >> chargeConc[lineIndex];
		++lineIndex;
	}
	infile.close();
}

void FileOperator::ReadTwoDimProblemInfo(int &gridNumX, int &gridNumY, TwoDimBC &left, TwoDimBC &right, TwoDimBC &up, TwoDimBC &down)
{
	fstream infile;
	infile.open(this->fileName.c_str(), ios::in);
	if (!infile)
		PrintConsole::Error("cannot open input file", this->fileName.c_str());

	string aLineBuffer = "";
	stringstream ss;
	string bcString = "";
	double tempValue = 0;

	for (int theLineNumber = 1; theLineNumber <= this->infoLinesTwoDim; ++theLineNumber)
	{
		getline(infile, aLineBuffer);
		ss.clear();
		ss.str(aLineBuffer);
		//the order of the file is left-right-up-down
		switch (theLineNumber)
		{
		case 1:
			ss >> gridNumX;
			ss >> gridNumY;
			break;
		case 2:
			ss >> bcString;
			left.SetType(bcString, PositionLeft);
			ss >> tempValue;
			left.SetValue(tempValue);//the value is 0 when it is artificial boundary with no value after
			break;
		case 3:
			ss >> bcString;
			right.SetType(bcString, PositionRight);
			ss >> tempValue;
			right.SetValue(tempValue);//the value is 0 when it is artificial boundary with no value after
			break;
		case 4:
			ss >> bcString;
			up.SetType(bcString, PositionUp);
			ss >> tempValue;
			up.SetValue(tempValue);//the value is 0 when it is artificial boundary with no value after
			break;
		case 5:
			ss >> bcString;
			down.SetType(bcString, PositionDown);
			ss >> tempValue;
			down.SetValue(tempValue);//the value is 0 when it is artificial boundary with no value after
			break;
		}
	}
	infile.close();
}

void FileOperator::ReadTwoDimProblem(std::vector<double> &meshx, std::vector<double> &meshy, My2DVector<double> &relativeDiel, My2DVector<double> &chargeConc)
{
	fstream infile;
	infile.open(this->fileName.c_str());
	if (!infile)
		PrintConsole::Error("cannot open input file", this->fileName.c_str());
	
	stringstream ss;
	string aLineBuffer = "";
	for (int iy = 0; iy < this->infoLinesTwoDim; ++iy)
	{
		getline(infile, aLineBuffer);
	}
	//get line of the mesh in x direction
	getline(infile, aLineBuffer);
	ss.clear();
	ss.str(aLineBuffer);
	for (std::vector<double>::size_type ix = 0; ix != meshx.size(); ++ix)
	{
		ss >> meshx[ix];
	}
	//get line of the mesh in y direction
	getline(infile, aLineBuffer);
	ss.clear();
	ss.str(aLineBuffer);
	for (std::vector<double>::size_type iy = 0; iy != meshy.size(); ++iy)
	{
		ss >> meshy[iy];
	}
	//data monitering
	//PrintConsole::PrintVector(meshy);
	
	//get the property of the grid
	int lineIndex = 0;
	int xx = 0;
	int yy = 0;
	while (getline(infile, aLineBuffer))
	{
		if (aLineBuffer == "") break;
		ss.clear();
		ss.str(aLineBuffer);
		ss >> xx; 
		ss >> yy;

		if ((xx != relativeDiel.GetX(lineIndex)) || (yy != relativeDiel.GetY(lineIndex)))
			PrintConsole::Error("Wrong input parameter in file", this->fileName.c_str());
		ss >> relativeDiel(lineIndex) >> chargeConc(lineIndex);
		++lineIndex;
	}
	infile.close();
	//for data monitoring
	//PrintConsole::PrintMy2DVector(relativeDiel);
	//PrintConsole::PrintMy2DVector(chargeConc);
	//PrintConsole::PrintVector(deltaX.DataVector);
}
